package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.app.dto.MyNewOrderDto;
import com.yami.shop.bean.app.dto.MyOrderDto;
import com.yami.shop.bean.app.dto.MyOrderItemDto;
import com.yami.shop.bean.enums.*;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.model.Station;
import com.yami.shop.bean.vo.DeliveryOrderVO;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageAdapter;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.dao.OrderMapper;
import com.yami.shop.dao.ShopDetailMapper;
import com.yami.shop.dao.StationMapper;
import com.yami.shop.service.DeliveryService;
import com.yami.shop.service.MyOrderService;
import com.yami.shop.service.ProductService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/09/15.
 */
@Service
@AllArgsConstructor
public class MyOrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements MyOrderService {

    private final OrderMapper orderMapper;
    private final StationMapper stationMapper;
    private final ShopDetailMapper shopDetailMapper;
    private final ProductService productService;
    private final DeliveryService deliveryService;

    @Override
    public IPage<MyOrderDto> pageMyOrderByUserIdAndStatus(Page<MyOrderDto> page, String userId, Integer status, String prodName) {
        List<MyOrderDto> myOrderDtos = orderMapper.listMyOrderByUserIdAndStatus(new PageAdapter(page), userId, status, prodName);
        setInfo(status, myOrderDtos);
        page.setRecords(myOrderDtos);
        page.setTotal(orderMapper.countMyOrderByUserIdAndStatus(userId, status, prodName, null, null));
        return page;
    }

    private void setInfo(Integer status, List<MyOrderDto> myOrderDtos) {
        boolean checkDeliveryNum = Objects.equals(status, OrderStatus.PADYED.value()) || Objects.equals(status, 0);
        Map<String, Integer> deliveryCountMap = new HashMap<>(16);
        if (checkDeliveryNum) {
            List<String> orderNumberList = myOrderDtos.stream().map(MyOrderDto::getOrderNumber).collect(Collectors.toList());
            List<DeliveryOrderVO> countList = deliveryService.listDeliveryCountByOrderNumber(orderNumberList);
            deliveryCountMap = countList.stream().collect(Collectors.toMap(DeliveryOrderVO::getOrderNumber, DeliveryOrderVO::getDeliveryCount));
        }
        for (MyOrderDto myOrderDto : myOrderDtos) {
            if (StrUtil.isBlank(myOrderDto.getShopName())) {
                myOrderDto.setShopName(Constant.PLATFORM_SHOP_NAME);
                myOrderDto.setShopId(Constant.PLATFORM_SHOP_ID);
            }
            // 如果是秒杀商品，则返回秒杀id
            if (Objects.equals(myOrderDto.getOrderType(), OrderType.SECKILL.value())) {
                Product prodDb = productService.getProductByProdId(myOrderDto.getOrderItemDtos().get(0).getProdId());
                if (Objects.equals(prodDb.getProdType(), ProdType.PROD_TYPE_SECKILL.value())) {
                    myOrderDto.setSeckillId(prodDb.getActivityId());
                }
            }
            if (checkDeliveryNum) {
                if (deliveryCountMap.containsKey(myOrderDto.getOrderNumber())) {
                    myOrderDto.setDeliveryCount(deliveryCountMap.get(myOrderDto.getOrderNumber()));
                }
            }

            List<MyOrderItemDto> orderItemDtos = myOrderDto.getOrderItemDtos();
            int score = 0;
            Set<String> giveawayIdsSet = null;
            Long mainOrderItemId = null;
            for (MyOrderItemDto orderItemDto : orderItemDtos) {
                score += orderItemDto.getUseScore() == null ? 0 : orderItemDto.getUseScore();
                // 设置赠品订单项的退款状态-用于判断是否可以评价
                if (Objects.equals(orderItemDto.getRefundType(), RefundType.SINGLE.value()) && Objects.equals(orderItemDto.getReturnMoneySts(), ReturnMoneyStsType.SUCCESS.value()) && StrUtil.isNotBlank(orderItemDto.getReturnGiveawayIds())) {
                    String returnGiveawayIds = orderItemDto.getReturnGiveawayIds();
                    String[] giveawayIds = returnGiveawayIds.split(StrUtil.COMMA);
                    giveawayIdsSet = new HashSet<>(Arrays.asList(giveawayIds));
                    mainOrderItemId = orderItemDto.getOrderItemId();
                }
            }
            if (CollectionUtil.isNotEmpty(giveawayIdsSet) && Objects.nonNull(mainOrderItemId)) {
                for (MyOrderItemDto orderItemDto : orderItemDtos) {
                    if (CollectionUtil.isEmpty(giveawayIdsSet)) {
                        break;
                    }
                    if (giveawayIdsSet.contains(orderItemDto.getOrderItemId().toString()) && Objects.equals(orderItemDto.getGiveawayOrderItemId(), mainOrderItemId)) {
                        orderItemDto.setRefundType(RefundType.SINGLE.value());
                        orderItemDto.setReturnMoneySts(ReturnMoneyStsType.SUCCESS.value());
                        giveawayIdsSet.remove(orderItemDto.getOrderItemId().toString());
                    }
                }
            }
            myOrderDto.setUserScore(score);
        }
    }

    @Override
    public IPage<MyOrderDto> pageMyOrderByParams(Page<MyOrderDto> page, String userId, Integer status, String orderName, Integer orderTimeStatus,
                                                 Integer orderType, String orderNumber, Long shopId, Integer orderMold) {
        String preTime = "";
        if (Objects.equals(OrderTimeStatusType.GROUP_BUY.value(), orderTimeStatus)) {
            preTime = getStatetime(7);
        }
        if (Objects.equals(OrderTimeStatusType.SECKILL.value(), orderTimeStatus) || Objects.equals(OrderTimeStatusType.ORDINARY.value(), orderTimeStatus)) {
            preTime = getReduceMonth(3);
        }
        List<MyOrderDto> myOrderDtoList = orderMapper.listMyOrderByParams(new PageAdapter(page), userId, status, orderName,
                orderTimeStatus, preTime, orderType, orderNumber, shopId, orderMold);
        setInfo(status, myOrderDtoList);
//        List<MyOrderDto> myOrderDtoList2 = myOrderDtoList.stream().filter(temp -> temp.getStatus().equals(OrderStatus.UNPAY.value())).collect(Collectors.toList());
//        List<String> orderNumbers = myOrderDtoList2.stream().map(MyOrderDto::getOrderNumber).collect(Collectors.toList());
//        payService.queryPay(orderNumbers);
        for (MyOrderDto myOrderDto : myOrderDtoList) {
            Map<Long, List<MyOrderItemDto>> map = myOrderDto.getOrderItemDtos().stream().filter(myOrderItemDto -> Objects.nonNull(myOrderItemDto.getGiveawayOrderItemId())).collect(Collectors.groupingBy(MyOrderItemDto::getGiveawayOrderItemId));
            // 如果没有赠品，就不需要处理
            if (MapUtil.isEmpty(map)) {
                continue;
            }
            // 将赠品放到对应的主订单项中
            Iterator<MyOrderItemDto> iterator = myOrderDto.getOrderItemDtos().iterator();
            while (iterator.hasNext()) {
                MyOrderItemDto myOrderItemDto = iterator.next();
                // 移除赠品的订单项，进入下一个循环
                if (Objects.nonNull(myOrderItemDto.getGiveawayOrderItemId())) {
                    iterator.remove();
                    continue;
                }
                // 主订单项插入赠品订单项
                if (map.containsKey(myOrderItemDto.getOrderItemId())) {
                    myOrderItemDto.setGiveawayList(map.get(myOrderItemDto.getOrderItemId()));
                }
            }
        }
        page.setRecords(myOrderDtoList);
        page.setTotal(orderMapper.countMyOrderByParams(userId, status, orderName, orderTimeStatus, preTime, orderType, orderNumber, shopId, orderMold));
        return page;
    }

    @Override
    public IPage<MyOrderDto> myOrderComment(PageParam<MyOrderDto> page, String userId) {
        List<MyOrderDto> myOrderDtos = orderMapper.orderCommentByUserIdAndStatus(new PageAdapter(page), userId);
        for (MyOrderDto myOrderDto : myOrderDtos) {
            if (StrUtil.isBlank(myOrderDto.getShopName())) {
                myOrderDto.setShopName(Constant.PLATFORM_SHOP_NAME);
            }
            List<MyOrderItemDto> orderItemDtos = myOrderDto.getOrderItemDtos();
            Set<Long> refundOrderItemIdSet = new HashSet<>();
            Map<Long, MyOrderItemDto> myOrderItemMap = new LinkedHashMap<>();
            for (MyOrderItemDto orderItemDto : orderItemDtos) {
                myOrderDto.setIsComm(orderItemDto.getCommSts());
                Long orderItemId = orderItemDto.getOrderItemId();
                myOrderItemMap.put(orderItemId, orderItemDto);
                // 找出单件退款成功的订单项Id，若同时有退款成功赠品，也记录相应的Id
                if (Objects.equals(orderItemDto.getRefundType(), RefundType.SINGLE.value()) && Objects.equals(orderItemDto.getReturnMoneySts(), ReturnMoneyStsType.SUCCESS.value()) && StrUtil.isNotBlank(orderItemDto.getReturnGiveawayIds())) {
                    String returnGiveawayIds = orderItemDto.getReturnGiveawayIds();
                    String[] giveawayIds = returnGiveawayIds.split(StrUtil.COMMA);
                    refundOrderItemIdSet.add(orderItemId);
                    for (String giveawayId : giveawayIds) {
                        refundOrderItemIdSet.add(Long.parseLong(giveawayId));
                    }
                }
            }
            // 如果退款成功的订单项Id集合非空，则移除相应的订单项
            if (CollectionUtil.isNotEmpty(refundOrderItemIdSet)) {
                refundOrderItemIdSet.forEach(orderItemId -> myOrderItemMap.remove(orderItemId));
            }
            ArrayList<MyOrderItemDto> myOrderItemDtos = new ArrayList<>(myOrderItemMap.values());
            System.out.println(myOrderItemMap.values());
            System.out.println(myOrderItemDtos);
            myOrderDto.setOrderItemDtos(new ArrayList<>(myOrderItemMap.values()));
        }
        page.setRecords(myOrderDtos);
        page.setTotal(orderMapper.countMyOrderByUserIdAndComm(userId));
        return page;
    }

    @Override
    public IPage<MyOrderItemDto> myOrderItemsComment(PageParam<MyOrderItemDto> page, String userId, Integer isComm) {
        List<MyOrderItemDto> myOrderDtos = orderMapper.orderItemCommentByUserIdAndStatus(new PageAdapter(page), userId, isComm);
        page.setRecords(myOrderDtos);
        page.setTotal(orderMapper.countOrderItemComment(userId, isComm));
        return page;
    }

    @Override
    public IPage<MyNewOrderDto> pageMyOrderByUserIdAndSuccess(Page<MyNewOrderDto> page, String userId,Long shopId) {
        List<MyNewOrderDto> myOrderDtos = orderMapper.pageMyOrderByUserIdAndSuccess(new PageAdapter(page), userId,shopId);
        page.setRecords(myOrderDtos);
        page.setTotal(orderMapper.countOrderSuccess(userId));
        return page;
    }

    @Override
    public IPage<MyOrderDto> getOrderListByStationId(PageParam<MyOrderDto> page, Long stationId, String userId) {
        Station station = stationMapper.selectOne(new LambdaQueryWrapper<Station>().eq(Station::getStationId, stationId).eq(Station::getStatus, 1));
        if (Objects.isNull(station)) {
            // 当前自提点门店不存在
            throw new YamiShopBindException("yami.station.no.exists");
        }
        page.setRecords(orderMapper.getOrderListByStationId(new PageAdapter(page), stationId, userId, station.getShopId()));
        page.setTotal(orderMapper.countOrderListByStationId(stationId, userId, station.getShopId()));
        return page;
    }

    @Override
    public IPage<MyOrderDto> getOrderListByShopId(PageParam<MyOrderDto> page, Long shopId, String userId) {
        ShopDetail shopDetail = shopDetailMapper.selectOne(new LambdaQueryWrapper<ShopDetail>().eq(ShopDetail::getShopId, shopId).eq(ShopDetail::getShopStatus, 1));
        if (Objects.isNull(shopDetail)) {
            // 未找到店铺信息
            throw new YamiShopBindException("yami.store.not.exist");
        }
        page.setRecords(orderMapper.getOrderListByStationId(new PageAdapter(page), null, userId, shopId));
        page.setTotal(orderMapper.countOrderListByStationId(null, userId, shopId));
        return page;
    }

    /**
     * 获取当前时间前7天的时间点
     */
    private String getStatetime(int reduce) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar c = Calendar.getInstance();
        // reduce = -7 前7天
        c.add(Calendar.DATE, -reduce);
        Date monday = c.getTime();
        String preMonday = sdf.format(monday);
        return preMonday;
    }

    /**
     * 获取当前时间 前三个月的时间点
     */
    private String getReduceMonth(int reduce) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar c = Calendar.getInstance();
        // reduce = -7 前7天
        c.add(Calendar.MONTH, -reduce);
        Date month = c.getTime();
        String priMonth = sdf.format(month);
        return priMonth;
    }
}
